package cn.fufeiii.bt.common.aspect.lock;

import java.lang.annotation.*;

/**
 * 全局锁
 * 详见{@link GlobalLockAspect}
 * <p>
 * 最终锁名：namespace + prefix + (key 或者 multipleKey)
 *
 * <p>
 * 锁名优先级：key > multipleKey
 * 回退优先级：fallback > defaultFallback
 *
 * @author FuFei
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface GlobalLock {

    /**
     * 固定锁前缀
     * 建议搭配{@link #key()}使用
     */
    String prefix() default "";

    /**
     * 锁名列表（支持sp-el表达式）
     * 若存在多个锁名，则会使用{@link org.redisson.RedissonMultiLock}
     * <p>
     * 默认值为[类名:方法名]
     */
    String[] key() default "";

    /**
     * 获取锁的最大等待时间(秒)
     * 只能填-1或者其他大于0的正值，否则会导致在多锁情况下{@link org.redisson.RedissonMultiLock}无法加锁
     */
    long waitTime() default -1;

    /**
     * 异常处理策略
     * SILENCE: 静默处理
     * FALLBACK: 回退处理
     * 注意：FALLBACK时，若不存在fallback方法则会抛出原异常（引发加锁逻辑失败的异常）
     */
    ExceptionHandleStrategy exceptionHandleStrategy() default ExceptionHandleStrategy.FALLBACK;

    /**
     * 加锁失败时的 默认 回退 方法
     * 优先级低于{@link #fallback()}，是一个通用的回退函数
     * defaultFallback函数出入参问题：
     * 1、函数入参 只能有一个和必须有一个{@code Exception}参数；2、出参类型一致（暂不考虑泛型）
     * <p>
     * 默认和原方法在同一个类中，也可使用{@link #fallbackClass()}指定其他类，此时注意函数必需为static函数
     */
    String defaultFallback() default "";

    /**
     * 加锁失败时的回退函数
     * fallback函数出入参问题：
     * 1、函数入参 必须和原函数一致 并 最后一个参数必须为{@code Exception}参数；2、出参类型一致（暂不考虑泛型）
     * <p>
     * 默认和原方法在同一个类中，也则可以指定{@link #fallbackClass()}类，注意对应的函数必需为static函数
     */
    String fallback() default "";

    /**
     * 加锁失败时的 指定 回退 类
     */
    Class<?> fallbackClass() default Void.class;

    /**
     * 枚举
     * 异常处理策略
     */
    enum ExceptionHandleStrategy {
        SILENCE, FALLBACK
    }

}
